import os

import requests

from .utils.snowflake_id import SnowflakeIDGenerator

snowflake_gen = SnowflakeIDGenerator(1, 1)


class Weixin:

    @classmethod
    def getAccessToken(cls, appid: str, secret: str) -> dict:
        """
        AssertionError: msg
        0       -> ok\n
        40029   -> js_code无效\n
        45011   -> API 调用太频繁，请稍候再试\n
        40226   -> 高风险等级用户，小程序登录拦截\n
        -1      -> 系统繁忙，此时请开发者稍候再试\n
        """
        ...

    @classmethod
    def getJsApiTicket(cls, access_token: str) -> dict:
        """
        AssertionError: msg
        0       -> ok\n
        40029   -> js_code无效\n
        45011   -> API 调用太频繁，请稍候再试\n
        40226   -> 高风险等级用户，小程序登录拦截\n
        -1      -> 系统繁忙，此时请开发者稍候再试\n
        """
        ...

    @classmethod
    def signJsApi(cls, jsapi_ticket: str, url: str) -> dict:
        """
        AssertionError: msg
        0       -> ok\n
        40029   -> js_code无效\n
        45011   -> API 调用太频繁，请稍候再试\n
        40226   -> 高风险等级用户，小程序登录拦截\n
        -1      -> 系统繁忙，此时请开发者稍候再试\n
        """

        ...


class Miniapp(Weixin):

    @classmethod
    def loginVerify(cls, appid: str, secret: str, code: str) -> tuple[bool, str | dict]:
        """
        AssertionError: msg
        0       -> ok\n
        40029   -> js_code无效\n
        45011   -> API 调用太频繁，请稍候再试\n
        40226   -> 高风险等级用户，小程序登录拦截\n
        -1      -> 系统繁忙，此时请开发者稍候再试\n
        """

        ...

    @classmethod
    def getPhoneNumber(cls, access_token: str, code: str) -> tuple[bool, str | dict]:
        """"
        AssertionError: msg

        0       -> ok\n
        40029   -> js_code无效\n
        45011   -> API 调用太频繁，请稍候再试\n
        40226   -> 高风险等级用户，小程序登录拦截\n
        -1      -> 系统繁忙，此时请开发者稍候再试\n
        """

        ...

    @classmethod
    def sendSubscribeMsg(cls, access_token: str, openid: str, template_id: str, page: str, miniprogram_state: str, data: dict):
        """
        AssertionError: msg
        0       -> ok\n
        40003   -> openid 无效\n
        40037   -> 模板id无效\n
        40038   -> 页面路径无效\n  
        40058   -> 模板数据字段不准确\n

        """

        ...


class ServiceNumber(Weixin):
    """
    微信服务号
    """

    class CustomMessagBody:
        ...

    @classmethod
    def loginVerify(cls, appid: str, secret: str, code: str):
        """
        AssertionError: msg
        0       -> ok\n
        40029   -> code无效\n
        """
        ...

    @classmethod
    def createQRCode(
        cls,
        access_token: str,
        action_name: str,
        scene_id: int = None,
        scene_str: str = None,
        expire_seconds: int = None
    ) -> dict:
        """
        创建二维码ticket,用于生成带参数的二维码
        ================================================================================================================
        Args:
            access_token: 微信公众号的access_token
        :param scene_id: 场景值ID,临时二维码时为32位非0整型,永久二维码时最大值为100000（目前参数只支持1--100000）
        :return: 返回的JSON数据包,包含ticket、expire_seconds、url
        ===============================================================================================================
        """
        ...

    @classmethod
    def decryptMessage(
        cls,
        from_xml: str,
        msg_sign: str,
        timestamp: str,
        nonce: str,
        token: str,
        encoding_aes_key: str
    ) -> str:
        """
        解密消息

        Args:
            from_xml: XML
            msg_sign: 签名串,对应URL参数的msg_signature
            timestamp: 时间戳,对应URL参数的timestamp
            nonce: 随机串,对应URL参数的nonce
            token: 微信公众号平台设置的token
            encoding_aes_key: 公众平台上,开发者设置的EncodingAESKey

        Returns:
            xml_content: 解密后的消息
        """
        ...

    @classmethod
    def sendCustomMessage(cls, openid: str, meg_body: CustomMessagBody):

        ...


class WechatPayV3:
    basedir = os.path.abspath(os.path.dirname(__file__))  # 获取当前目录

    @classmethod
    def calculateMD5(cls, s: str) -> str:
        """
        计算字符串的MD5值。

        :param s: 字符串
        :return: MD5 哈希值的十六进制字符串
        """
        ...

    def __init__(self,
                 app_id: str,
                 mch_id: str,
                 private_key: str,
                 api_v3_key: str,
                 serial_no: str,
                 notify_url: str,
                 private_key_password: str = None,
                 certificates_path: str = None,
                 ignore_resp_sign=False
                 ):
        """
        :param ignore_resp_sign: 是否忽略应答验签(用于第一次缓存证书)
        """
        ...

    def _auth(self, req: requests.Request) -> requests.Response:
        """
        ==构造签名串==
        """
        ...

    @classmethod
    def genOutTradeNO(cls, trade_type="jsapi", nacl=None) -> str:
        """
        生成商户订单号
        :param trade_type: 交易类型
        :param nacl: 盐
        """
        ...

    def paySign(self, prepay_id: str, nonce_str: str = None) -> dict:
        ...

    def sign(self, s: str) -> str:
        """
        签名串需经过SHA256withRSA签名后，再经过Base64编码
        :param s: 待签名串
        :param private_key: 私钥
        :param private_key_password: 私钥密码,如果私钥有密码，请提供
        """
        ...

    @classmethod
    def respSign(cls, timestamp: str, nonce: str, body: str, cer: bytes, signature) -> None | str:
        """
        验签
        :param timestamp: 时间戳
        :param nonce: 随机字符串
        :param body: 应答内容
        """
        ...

    def getCertificates(self):
        """下载证书"""
        ...

    def getCertificateBySerialNO(self, serial_no) -> bytes:
        """读取缓存证书"""
        ...

    def decryptAesGcm(self, nonce, ciphertext, associated_data) -> bytes:
        ...

    def jsapiPay(
            self,
            openid,
            price,
            out_trade_no,
            currency="CNY",
            description="测试jsapi支付",
            attach=None
    ) -> str:
        """
        小程序支付
        :param openid: 用户openid
        :param price: 订单总金额，单位为分
        :param out_trade_no: 商户订单号
        :param description: 商品描述
        :param attach: 商户数据包
        """
        ...

    def queryOrder(self, out_trade_no=None, transaction_id=None):
        ...
